home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1999 / MacHack 1999.toast / The Hacks / Rotato / Source / ShowInitIcon.c < prev    next >
Encoding:
Text File  |  1999-06-25  |  5.7 KB  |  155 lines  |  [TEXT/CWIE]

  1. // ShowInitIcon - version 1.0.1, May 30th, 1995
  2. // This code is intended to let INIT writers easily display an icon at startup time.
  3. // View in Geneva 9pt, 4-space tabs
  4.  
  5. // Written by: Peter N Lewis <peter@mail.peter.com.au>, Jim Walker <JWWalker@aol.com>
  6. // and François Pottier <pottier@dmi.ens.fr>, with thanks to previous ShowINIT authors.
  7. // Send comments and bug reports to François Pottier.
  8.  
  9. // This version features:
  10. // - Short and readable code.
  11. // - Correctly wraps around when more than one row of icons has been displayed.
  12. // - works with System 6
  13. // - Built with Universal Headers & CodeWarrior. Should work with other headers/compilers.
  14.  
  15. #include <Memory.h>
  16. #include <Resources.h>
  17. #include <Icons.h>
  18. #include <OSUtils.h>
  19. #include "ShowInitIcon.h"
  20.  
  21. // You should set SystemSixOrLater in your headers to avoid including glue for SysEnvirons.
  22.  
  23. // ---------------------------------------------------------------------------------------------------------------------
  24. // Set this flag to 1 if you want to compile this file into a stand-alone resource (see note below).
  25. // Set it to 0 if you want to include this source file into your INIT project.
  26.  
  27. #if 0
  28. #define ShowInitIcon main
  29. #endif
  30.  
  31. // ---------------------------------------------------------------------------------------------------------------------
  32. // The ShowINIT mechanism works by having each INIT read/write data from these globals.
  33. // The MPW C compiler doesn't accept variables declared at an absolute address, so I use these macros instead.
  34. // Only one macro is defined per variable; there is no need to define a Set and a Get accessor like in <LowMem.h>.
  35.  
  36. #define    LMVCoord            (* (short*) 0x92A)
  37. #define    LMVCheckSum        (* (short*) 0x928)
  38. #define    LMHCoord            (* (short*) 0x92C)
  39. #define    LMHCheckSum        (* (short*) 0x92E)
  40.  
  41. // ---------------------------------------------------------------------------------------------------------------------
  42. // Prototypes for the subroutines. The main routine comes first; this is necessary to make THINK C's "Custom Header" option work.
  43.  
  44. static unsigned short CheckSum (unsigned short x);
  45. static void ComputeIconRect (Rect* iconRect, Rect* screenBounds);
  46. static void AdvanceIconPosition (Rect* iconRect);
  47. static void DrawBWIcon (short iconID, Rect *iconRect);
  48.  
  49. // ---------------------------------------------------------------------------------------------------------------------
  50. // Main routine.
  51.  
  52. typedef struct {
  53.     QDGlobals            qd;                                    // Storage for the QuickDraw globals
  54.     long                qdGlobalsPtr;                            // A5 points to this place; it will contain a pointer to qd
  55. } QDStorage;
  56.  
  57. pascal void ShowInitIcon (short iconFamilyID, Boolean advance)
  58. {
  59.     CGrafPort            colorPort;
  60.     GrafPort            bwPort;
  61.     Rect                destRect;
  62.     SysEnvRec        environment;                            // Machine configuration.
  63.  
  64.     InitGraf(&qd.thePort);                                    // Initialize the fake QD Globals
  65.     SysEnvirons(curSysEnvVers, &environment);                    // Find out what kind of machine this is
  66.  
  67.     ComputeIconRect(&destRect, &qd.screenBits.bounds);            // Compute where the icon should be drawn
  68.  
  69.     if (environment.systemVersion >= 0x0700 && environment.hasColorQD) {
  70.         OpenCPort(&colorPort);
  71.         PlotIconID(&destRect, atNone, ttNone, iconFamilyID);
  72.         CloseCPort(&colorPort);
  73.     }
  74.     else {
  75.         OpenPort(&bwPort);
  76.         DrawBWIcon(iconFamilyID, &destRect);
  77.         ClosePort(&bwPort);
  78.     }
  79.     
  80.     if (advance)
  81.         AdvanceIconPosition (&destRect);
  82. }
  83.  
  84. // ---------------------------------------------------------------------------------------------------------------------
  85. // A checksum is used to make sure that the data in there was left by another ShowINIT-aware INIT.
  86.  
  87. static unsigned short CheckSum (unsigned short x)
  88. {
  89.     return ((x << 1) | (x >> 15)) ^ 0x1021;
  90. }
  91.  
  92. // ---------------------------------------------------------------------------------------------------------------------
  93. // ComputeIconRect computes where the icon should be displayed.
  94.  
  95. static void ComputeIconRect (Rect* iconRect, Rect* screenBounds)
  96. {
  97.     if (CheckSum(LMHCoord) != LMHCheckSum)                    // If we are first, we need to initialize the shared data.
  98.         LMHCoord = 8;
  99.     if (CheckSum(LMVCoord) != LMVCheckSum)
  100.         LMVCoord = screenBounds->bottom - 40;
  101.     
  102.     if (LMHCoord + 34 > screenBounds->right) {                    // Check whether we must wrap
  103.         iconRect->left = 8;
  104.         iconRect->top = LMVCoord - 40;
  105.     }
  106.     else {
  107.         iconRect->left = LMHCoord;
  108.         iconRect->top = LMVCoord;
  109.     }
  110.     iconRect->right = iconRect->left + 32;
  111.     iconRect->bottom = iconRect->top + 32;
  112. }
  113.  
  114. // AdvanceIconPosition updates the shared global variables so that the next extension will draw its icon beside ours.
  115.  
  116. static void AdvanceIconPosition (Rect* iconRect)
  117. {
  118.     LMHCoord = iconRect->left + 40;                            // Update the shared data
  119.     LMVCoord = iconRect->top;
  120.     LMHCheckSum = CheckSum(LMHCoord);
  121.     LMVCheckSum = CheckSum(LMVCoord);
  122. }
  123.  
  124. // DrawBWIcon draws the 'ICN#' member of the icon family. It works under System 6.
  125.  
  126. static void DrawBWIcon (short iconID, Rect *iconRect)
  127. {
  128.     Handle        icon;
  129.     BitMap        source, destination;
  130.     GrafPtr        port;
  131.     
  132.     icon = Get1Resource('ICN#', iconID);
  133.     if (icon != NULL) {
  134.         HLock(icon);
  135.                                                         // Prepare the source and destination bitmaps.
  136.         source.baseAddr = *icon + 128;                        // Mask address.
  137.         source.rowBytes = 4;
  138.         SetRect(&source.bounds, 0, 0, 32, 32);
  139.         GetPort(&port);
  140.         destination = port->portBits;
  141.                                                         // Transfer the mask.
  142.         CopyBits(&source, &destination, &source.bounds, iconRect, srcBic, nil);
  143.                                                         // Then the icon.
  144.         source.baseAddr = *icon;
  145.         CopyBits(&source, &destination, &source.bounds, iconRect, srcOr, nil);
  146.     }
  147. }
  148.  
  149. // ---------------------------------------------------------------------------------------------------------------------
  150. // Notes
  151.  
  152. // Checking for PlotIconID:
  153. // We (PNL) now check for system 7 and colour QD, and use colour graf ports and PlotIconID only if both are true
  154. // Otherwise we use B&W grafport and draw using PlotBWIcon.
  155.